package com.pencilisland.pay.mgt.app.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.pencilisland.pay.api.bean.constant.OrderConstant;
import com.pencilisland.pay.api.bean.mp.core.UpdateOrderREQ;
import com.pencilisland.pay.api.bean.mp.core.UpdateOrderRES;
import com.pencilisland.pay.mgt.app.entity.OrderInfoEntity;
import com.pencilisland.pay.mgt.app.entity.OrderInfoEntity_;
import com.pencilisland.pay.mgt.app.entity.TenantEntity;
import com.pencilisland.pay.mgt.app.repository.OrderInfoRepository;
import com.pencilisland.pay.mgt.app.repository.TenantRepository;
import com.pencilisland.pay.mgt.app.service.OrderService;
import com.pencilisland.pay.mgt.app.service.RestService;
import com.pencilisland.pay.mgt.console.entity.SysUser;
import com.pencilisland.pay.mgt.console.service.UserService;
import com.pencilisland.pay.mgt.util.G;

@Component
public class OrderServiceImpl implements OrderService {
	
	Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	UserService userService;
	@Autowired
	OrderInfoRepository orderInfoRepo;
	@Autowired
	TenantRepository tenantRepo;
	@Autowired
	RestService restService;

	@Override
	public Page<OrderInfoEntity> orderList(final OrderInfoEntity cretiria, int start, int limit) {

		Specification<OrderInfoEntity> spec = new Specification<OrderInfoEntity>() {

			@Override
			public Predicate toPredicate(Root<OrderInfoEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				// 判断是否是商户
				SysUser user = userService.findSessionUser();
				TenantEntity tenant = tenantRepo.findByUserId(user.getUserId());
				if (tenant != null) {
					list.add(cb.equal(root.get(OrderInfoEntity_.tenantCode), tenant.getCode()));
				}
				if (!StringUtils.isEmpty(cretiria.getStatus())) {
					list.add(cb.equal(root.get(OrderInfoEntity_.status), cretiria.getStatus()));
				}
				if (!StringUtils.isEmpty(cretiria.getOrderNo())) {
					list.add(cb.equal(root.get(OrderInfoEntity_.orderNo), cretiria.getOrderNo()));
				}
				if (!StringUtils.isEmpty(cretiria.getCreateDateStart())) {
					String time = cretiria.getCreateDateStart().replace("-", "") + "000000";
					list.add(cb.greaterThanOrEqualTo(root.get(OrderInfoEntity_.createTime), time));
				}
				if (!StringUtils.isEmpty(cretiria.getCreateDateEnd())) {
					String time = cretiria.getCreateDateStart().replace("-", "") + "235959";
					list.add(cb.lessThanOrEqualTo(root.get(OrderInfoEntity_.createTime), time));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.DESC, OrderInfoEntity_.createTime.getName()));

		Pageable pageable = new PageRequest(start / limit, limit, sort);

		return orderInfoRepo.findAll(spec, pageable);

	}

	@Override
	public OrderInfoEntity loadData(String orderNo) {
		return orderInfoRepo.findOne(orderNo);
	}

	@Override
	public void cancel(String orderNos, String remark) {
		String[] orderNoArray = orderNos.split(",");
		List<OrderInfoEntity> orderInfos = new ArrayList<OrderInfoEntity>();
		for (int i = 0; i < orderNoArray.length; i++) {
			OrderInfoEntity orderInfo = orderInfoRepo.findOne(orderNoArray[i]);
			if (orderInfo.getStatus() == OrderConstant.STATUS_1) {
				orderInfo.setStatus(OrderConstant.STATUS_3);
				orderInfo.setRemark(remark);
				orderInfos.add(orderInfo);
			} else if (orderInfo.getStatus() == OrderConstant.STATUS_0) {
				orderInfo.setStatus(OrderConstant.STATUS_4);
				orderInfo.setRemark(remark);
				orderInfos.add(orderInfo);
			} else {
				continue;
			}
		}

		if (!orderInfos.isEmpty()) {
			UpdateOrderREQ updateOrderReq = new UpdateOrderREQ();
			List<UpdateOrderREQ.ElementOrders> orders = new ArrayList<UpdateOrderREQ.ElementOrders>();
			for (OrderInfoEntity orderInfo : orderInfos) {
				UpdateOrderREQ.ElementOrders elementOrders = new UpdateOrderREQ.ElementOrders();
				elementOrders.setOrderNo(orderInfo.getOrderNo());
				elementOrders.setStatus(orderInfo.getStatus());
				orders.add(elementOrders);
			}
			updateOrderReq.setOrders(orders);

			UpdateOrderRES updateOrderRes = restService.sendToCoreMP("updateOrder", updateOrderReq,
					UpdateOrderRES.class);
			if (updateOrderRes != null && updateOrderRes.getSuccess()) {
				orderInfoRepo.save(orderInfos);
			}
		}
	}

	@Override
	public void send(String orderNos, String trackingNumber, String remark) {
		String[] orderNoArray = orderNos.split(",");
		List<OrderInfoEntity> orderInfos = new ArrayList<OrderInfoEntity>();
		for (int i = 0; i < orderNoArray.length; i++) {
			OrderInfoEntity orderInfo = orderInfoRepo.findOne(orderNoArray[i]);
			if (orderInfo.getStatus() == OrderConstant.STATUS_1) {
				orderInfo.setStatus(OrderConstant.STATUS_2);
				orderInfo.setTrackingNumber(trackingNumber);
				orderInfo.setRemark(remark);
				orderInfos.add(orderInfo);
			} else {
				continue;
			}

		}

		if (!orderInfos.isEmpty()) {
			UpdateOrderREQ updateOrderReq = new UpdateOrderREQ();
			List<UpdateOrderREQ.ElementOrders> orders = new ArrayList<UpdateOrderREQ.ElementOrders>();
			for (OrderInfoEntity orderInfo : orderInfos) {
				UpdateOrderREQ.ElementOrders elementOrders = new UpdateOrderREQ.ElementOrders();
				elementOrders.setOrderNo(orderInfo.getOrderNo());
				elementOrders.setStatus(orderInfo.getStatus());
				elementOrders.setRemark(orderInfo.getRemark());
				elementOrders.setTrackingNumber(orderInfo.getTrackingNumber());
				orders.add(elementOrders);
			}
			updateOrderReq.setOrders(orders);

			UpdateOrderRES updateOrderRes = restService.sendToCoreMP("updateOrder", updateOrderReq,
					UpdateOrderRES.class);
			if (updateOrderRes != null && updateOrderRes.getSuccess()) {
				orderInfoRepo.save(orderInfos);
			}
		}

	}

	@Override
	public void buildKuaidi100Excel(Workbook workbook, final OrderInfoEntity cretiria) {

		Specification<OrderInfoEntity> spec = new Specification<OrderInfoEntity>() {

			@Override
			public Predicate toPredicate(Root<OrderInfoEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				// 判断是否是商户
				SysUser user = userService.findSessionUser();
				TenantEntity tenant = tenantRepo.findByUserId(user.getUserId());
				if (tenant != null) {
					list.add(cb.equal(root.get(OrderInfoEntity_.tenantCode), tenant.getCode()));
				}
				if (!StringUtils.isEmpty(cretiria.getStatus())) {
					list.add(cb.equal(root.get(OrderInfoEntity_.status), cretiria.getStatus()));
				}
				if (!StringUtils.isEmpty(cretiria.getOrderNo())) {
					list.add(cb.equal(root.get(OrderInfoEntity_.orderNo), cretiria.getOrderNo()));
				}
				if (!StringUtils.isEmpty(cretiria.getCreateDateStart())) {
					String time = cretiria.getCreateDateStart().replace("-", "") + "000000";
					list.add(cb.greaterThanOrEqualTo(root.get(OrderInfoEntity_.createTime), time));
				}
				if (!StringUtils.isEmpty(cretiria.getCreateDateEnd())) {
					String time = cretiria.getCreateDateStart().replace("-", "") + "235959";
					list.add(cb.lessThanOrEqualTo(root.get(OrderInfoEntity_.createTime), time));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.DESC, OrderInfoEntity_.createTime.getName()));

		List<OrderInfoEntity> orderInfos = orderInfoRepo.findAll(spec,sort);

		if(orderInfos!=null&&!orderInfos.isEmpty()){
			Sheet sheet = workbook.getSheetAt(0);
			Integer rowNum=1;
			for(OrderInfoEntity orderInfo:orderInfos){
				Row row = sheet.createRow(rowNum);
				Cell cell0 = row.createCell(0);
				cell0.setCellValue(orderInfo.getUserName());
				Cell cell1 = row.createCell(1);
				cell1.setCellValue(orderInfo.getTelNumber());
				
				Cell cell2 = row.createCell(2);
				cell2.setCellValue("");
				
				StringBuilder addressBuilder = new StringBuilder();
				addressBuilder.append(orderInfo.getProvinceName())
				              .append(orderInfo.getCityName())
				              .append(orderInfo.getCountyName())
				              .append(orderInfo.getDetailInfo());
				
				Cell cell3 = row.createCell(3);
				cell3.setCellValue(addressBuilder.toString());
				
				Cell cell4 = row.createCell(4);
				cell4.setCellValue("");
				
				Cell cell5 = row.createCell(5);
				cell5.setCellValue(orderInfo.getGoodsName());
				
				Cell cell6 = row.createCell(6);
				cell6.setCellValue("申通");
				
				Cell cell7 = row.createCell(7);
				cell7.setCellValue("");
				
				Cell cell8 = row.createCell(8);
				cell8.setCellValue("");
				
				Cell cell9 = row.createCell(9);
				cell9.setCellValue("");
				
				Cell cell10 = row.createCell(10);
				cell10.setCellValue("");
				
				Cell cell11 = row.createCell(11);
				cell11.setCellValue("小铅笔");
				
				Cell cell12 = row.createCell(12);
				cell12.setCellValue("010-58679543");
				
				Cell cell13 = row.createCell(13);
				cell13.setCellValue("铅笔岛");
				
				Cell cell14 = row.createCell(14);
				cell14.setCellValue("北京朝阳区北京市朝阳区时间国际4号楼1503室");
				
				rowNum++;
			}
		}

	}

	@Override
	public void buildZhongtongExcel(Workbook workbook, OrderInfoEntity cretiria) {


		Specification<OrderInfoEntity> spec = new Specification<OrderInfoEntity>() {

			@Override
			public Predicate toPredicate(Root<OrderInfoEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				// 判断是否是商户
				SysUser user = userService.findSessionUser();
				TenantEntity tenant = tenantRepo.findByUserId(user.getUserId());
				if (tenant != null) {
					list.add(cb.equal(root.get(OrderInfoEntity_.tenantCode), tenant.getCode()));
				}
				if (!StringUtils.isEmpty(cretiria.getStatus())) {
					list.add(cb.equal(root.get(OrderInfoEntity_.status), cretiria.getStatus()));
				}
				if (!StringUtils.isEmpty(cretiria.getOrderNo())) {
					list.add(cb.equal(root.get(OrderInfoEntity_.orderNo), cretiria.getOrderNo()));
				}
				if (!StringUtils.isEmpty(cretiria.getCreateDateStart())) {
					String time = cretiria.getCreateDateStart().replace("-", "") + "000000";
					list.add(cb.greaterThanOrEqualTo(root.get(OrderInfoEntity_.createTime), time));
				}
				if (!StringUtils.isEmpty(cretiria.getCreateDateEnd())) {
					String time = cretiria.getCreateDateStart().replace("-", "") + "235959";
					list.add(cb.lessThanOrEqualTo(root.get(OrderInfoEntity_.createTime), time));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.DESC, OrderInfoEntity_.createTime.getName()));

		List<OrderInfoEntity> orderInfos = orderInfoRepo.findAll(spec,sort);

		if(orderInfos!=null&&!orderInfos.isEmpty()){
			Sheet sheet = workbook.getSheetAt(0);
			Integer rowNum=1;
			for(OrderInfoEntity orderInfo:orderInfos){
				Row row = sheet.createRow(rowNum);
				Cell cell0 = row.createCell(0);
				cell0.setCellValue("");
				Cell cell1 = row.createCell(1);
				cell1.setCellValue("");
				
				Cell cell2 = row.createCell(2);
				cell2.setCellValue("小铅笔");
				
				Cell cell3 = row.createCell(3);
				cell3.setCellValue("010-58679543");
				
				Cell cell4 = row.createCell(4);
				cell4.setCellValue("");
				
				Cell cell5 = row.createCell(5);
				cell5.setCellValue("");
				
				Cell cell6 = row.createCell(6);
				cell6.setCellValue("");
				
				Cell cell7 = row.createCell(7);
				cell7.setCellValue("北京朝阳区北京市朝阳区时间国际4号楼1503室");
				
				Cell cell8 = row.createCell(8);
				cell8.setCellValue(orderInfo.getUserName());
				
				Cell cell9 = row.createCell(9);
				cell9.setCellValue(orderInfo.getTelNumber());
				
				Cell cell10 = row.createCell(10);
				cell10.setCellValue("");
				
				Cell cell11 = row.createCell(11);
				cell11.setCellValue("");
				
				Cell cell12 = row.createCell(12);
				cell12.setCellValue("");
				
				StringBuilder addressBuilder = new StringBuilder();
				addressBuilder.append(orderInfo.getProvinceName())
				              .append(orderInfo.getCityName())
				              .append(orderInfo.getCountyName())
				              .append(orderInfo.getDetailInfo());
				Cell cell13 = row.createCell(13);
				cell13.setCellValue(addressBuilder.toString());
				
				Cell cell14 = row.createCell(14);
				cell14.setCellValue(orderInfo.getGoodsName());
				
				Cell cell37 = row.createCell(37);
				cell37.setCellValue(orderInfo.getOrderNo());
				
				rowNum++;
			}
		}
	}

	@Override
	public void importZhongtong(MultipartFile file) throws Exception{
		Workbook wb = new XSSFWorkbook(file.getInputStream());
		Sheet sheet = wb.getSheetAt(0);
		
		final List<Map<String,Object>> dataList = new ArrayList<Map<String,Object>>();
		
		sheet.rowIterator().forEachRemaining(new Consumer<Row>() {
			@Override
			public void accept(Row row) {
				if(row.getRowNum()!=0){
					Cell cell7= row.getCell(7);
					String trackingNumber = cell7.getStringCellValue();
					Cell cell8 = row.getCell(8);
					String orderNo = cell8.getStringCellValue();
					
					if(!StringUtils.isEmpty(trackingNumber)&&!StringUtils.isEmpty(orderNo)){
						Map<String,Object> data = new HashMap<String,Object>();
						data.put("trackingNumber", trackingNumber);
						data.put("orderNo", orderNo);
						dataList.add(data);
					}
				}
				
			}
		});
		
		List<OrderInfoEntity> orderInfos = new ArrayList<OrderInfoEntity>();
		for (int i = 0; i < dataList.size(); i++) {
			Map<String,Object> data = dataList.get(i);
			OrderInfoEntity orderInfo = orderInfoRepo.findOne(G.str(data.get("orderNo")));
			if (orderInfo!=null&&StringUtils.isEmpty(orderInfo.getTrackingNumber())) {
				orderInfo.setStatus(OrderConstant.STATUS_2);
				orderInfo.setTrackingNumber(G.str(data.get("trackingNumber")));
				orderInfo.setRemark("中通导入 ");
				orderInfos.add(orderInfo);
			} else {
				log.info("导入不做处理【{}】【{}】",G.str(data.get("orderNo")),G.str(data.get("trackingNumber")));
				continue;
			}

		}

		if (!orderInfos.isEmpty()) {
			UpdateOrderREQ updateOrderReq = new UpdateOrderREQ();
			List<UpdateOrderREQ.ElementOrders> orders = new ArrayList<UpdateOrderREQ.ElementOrders>();
			for (OrderInfoEntity orderInfo : orderInfos) {
				UpdateOrderREQ.ElementOrders elementOrders = new UpdateOrderREQ.ElementOrders();
				elementOrders.setOrderNo(orderInfo.getOrderNo());
				elementOrders.setStatus(orderInfo.getStatus());
				elementOrders.setRemark(orderInfo.getRemark());
				elementOrders.setTrackingNumber(orderInfo.getTrackingNumber());
				orders.add(elementOrders);
			}
			updateOrderReq.setOrders(orders);

			UpdateOrderRES updateOrderRes = restService.sendToCoreMP("updateOrder", updateOrderReq,
					UpdateOrderRES.class);
			if (updateOrderRes != null && updateOrderRes.getSuccess()) {
				orderInfoRepo.save(orderInfos);
			}
		}
		
	}

}
